前二天,我們透過Router接不同的Network連接起來,讓不同的Network上的VM可以通訊,但是,這樣仍無法讓VM能夠連到網際網路。在OpenStack裡,透過一種特殊的Network,我們稱它External
Network, 讓VM可以透過External network 連到網際網路。External Network也是OpenStack的一個Network,如果要讓VM透過external network 上網的話,有二種作法,我們今天先介紹第一種,也是最常見的作法,就是透過Router連接一般的Network與External network;第二種則是讓VM直接使用External Network,這我們過二天再和大家說明。
今天介紹OVN的內容,會和Day-07: 透過SNAT與DNAT 連至Internet的SNAT內容有關連,忘記的讀者,可以先回去複習一下,效果會更好喔。
今天要建立的網路架構如下,透過一個Router將二個Network 連接起來,只是圖中右手邊的Network,是一個External Network,且會透過10.0.2.2 這個gateway 連到網際網路。而在router 與external network連接的介面上,會分配一個10.0.2.211的IP。
openstack network create --provider-network-type geneve --provider-segment 123 n1
openstack subnet create --subnet-range 172.16.100.0/24 --network n1 n1subnet
openstack network create --provider-network-type flat --provider-physical-network extnet0 ext_n2 \
--external
# for VirtualBox
SUBNET_RANGE=10.0.2.0/24
GATEWAY=10.0.2.2
ALLOCATION_RANGE=start=10.0.2.210,end=10.0.2.220
openstack subnet create --subnet-range ${SUBNET_RANGE} --network ext_n2 extsubnet \
--no-dhcp \
--gateway ${GATEWAY} \
--allocation-pool ${ALLOCATION_RANGE}
External network都是要做為和網際網路連線之用,所以一定會使用到實體線路,要使用實體線路的話,Network 的type就只能用flat 或 vlan,這邊我們是選用flat。所以建立External Network和建一個flat Network基本上是一樣的,唯二的差別就在於
--external
告訴OpenStack,這個network是一個external network。extnet0
,而不是之前用的flat0
。這裡要回去複一下使用packstack建立OpenStack的二個參數--os-neutron-ovn-bridge-mappings=extnet0:br-ex,flat0:br-eth2
與 --os-neutron-ovn-bridge-interfaces=br-ex:eth0,br-eth2:eth2
,因為今天是要對外上網,使用的NIC是eth0,而eth0所對應到的bridge是extnet0
。External Network的subnet,通常要照實體網路的狀況進行設定,否則就會無法上網。
IMAGE_ID=$(openstack image show cirros --format json | jq -r .id)
openstack server create --nic net-id=n1,v4-fixed-ip=172.16.100.10 --flavor m1.nano --image $IMAGE_ID vm_1
openstack router create r
openstack router add subnet r n1subnet
openstack router set r --external-gateway ext_n2
以OpenStack的角度來看,仍是將二個Network連在一個router上,但是用的指令則不太一樣。要連接External Network,是設定 router的--external-gateway
屬性。
可以看出,flat Network是做為External Network。
# Network
openstack network list --long -c ID -c "Network Type" -c "Router Type" | abbrev
+--------+--------------+-------------+
| ID | Network Type | Router Type |
+--------+--------------+-------------+
| 76af9b | geneve | Internal |
| 4914b0 | flat | External |
+--------+--------------+-------------+
External Network上的Port和一般的Network相比,有二個特殊的地方:
network:router_gateway
的port,這是external network特有的port, 是要與實體網路的gateway連接network:distributed
的Port 沒有IP,因為這個Port主要是給metadata service使用,我們目前沒有將VM直接放在External Network上,所以沒有相對應的IP被建立出來。# Port
openstack port list --long -c ID -c "Fixed IP Addresses" -c "Device Owner" | abbrev
+--------+-------------------------------------------------+--------------------------+
| ID | Fixed IP Addresses | Device Owner |
+--------+-------------------------------------------------+--------------------------+
| 0bece6 | ip_address='172.16.100.10' , subnet_id='ec52a9' | compute:nova |
| 06ff4f | ip_address='172.16.100.2' , subnet_id='ec52a9' | network:distributed |
| 1c52f2 | ip_address='172.16.100.1' , subnet_id='ec52a9' | network:router_interface |
| e70e83 | | network:distributed |
| 268c32 | ip_address='10.0.2.211' , subnet_id='6f6c62' | network:router_gateway |
+--------+-------------------------------------------------+--------------------------+
接下來,來看一下OVN上建立出來的元件長像。左手邊的logical switch對應到geneve Network,這個和之前的例子相同,沒有新的變化。右手邊的logical switch對應到的flat network, 也與Day-17: Flat Tenant Network的介紹相同喔,差別在於現在是對應至extnet0
這個實體網路。
而在logical router上,可以查到SNAT的設定,表示logical router會將來自 172.16.100.0/24的IP,做SNAT而達到連線至網際網路。
router_name=$(ovn-nbctl --format json --columns name list logical_router | jq -cr .data[][])
ovn-nbctl lr-nat-list $router_name
TYPE GATEWAY_PORT EXTERNAL_IP EXTERNAL_PORT LOGICAL_IP EXTERNAL_MAC LOGICAL_PORT
snat 10.0.2.211 172.16.100.0/24
直接查看logical router的資訊,也可以看到一筆nat的設定。
ovn-nbctl show $router_name| abbrev
router 1a0898 (neutron-e80dc4) (aka r)
port lrp-1c52f2
mac: "fa:16:3e:d0:74:be"
networks: ["172.16.100.1/24"]
port lrp-268c32
mac: "fa:16:3e:84:56:22"
networks: ["10.0.2.211/24"]
gateway chassis: [1cea77]
nat 643964
external ip: "10.0.2.211"
logical ip: "172.16.100.0/24"
type: "snat"
我們再來看看compute node與network-controller node上bridge的情況。這裡先注意到,在所有的node上皆有br-eth2 這個bridge,但是只有在network-controller node上有br-ex這個bridge。因為network-controller node是network node,如果沒有br-ex,其他節點上的VM就無法透過br-ex連到網際網路;如果network-controller node沒有br-eth2,當VM建立在flat Network上,就無法到達network-controller node, 以致於無法上網。但是,為什麼br-eth2會建立在每個節點上呢? 還記得packstack使用的參數嗎?其中的--os-neutron-ovn-bridges-compute=br-eth2
就在宣告,在每個節點上要建立出那些bridge。
--os-neutron-ovn-bridge-mappings=extnet0:br-ex,flat0:br-eth2 \
--os-neutron-ovn-bridge-interfaces=br-ex:eth0,br-eth2:eth2 \
--os-neutron-ovn-bridges-compute=br-eth2 \
再來,單獨來看network-controller node上的br-ex, 可以看到有一對patch port,這個patch port的功用,就是用來連接extnet0
這個實體網路,其實和Day-17: Flat Tenant Network裡針對flat0的介紹也是相同的,讓大家自行練習解讀吧。另外,可能有人可能會問,為什麼目前在每個node上的br-eth2上都沒有patch port呢? 這是因為我們並沒有建立使用到br-eth2的flat network阿, 所以在 br-eth2上就不會出現patch port。
今天的最後,我們來看一下,在compute-01上的VM,如何透過network-controller node上的br-ex連線到網際網路。
compute-01 本身可以利用eth0 上網,但是在eth0 上,沒有發現VM對外的流量,這就表示VM不會直接透過compute-01本身的eth0上網
tcpdump -i eth0 icmp # 抓不到封包
但是,在geneve tunnel上,可以發現geneve 封裝後的ICMP request封包,送往network-controller node;也會看到由network-controller 送回來的ICMP reply。
tcpdump -vvneei eth1 'udp port 6081'
11:39:34.402066 52:54:00:ea:65:ed > 52:54:00:82:23:6d, ethertype IPv4 (0x0800), length 156: (tos 0x0, ttl 64, id 22519, offset 0, flags [DF], proto UDP (17), length 142)
192.168.33.20.51362 > 192.168.33.10.geneve: [bad udp cksum 0xc3fa -> 0x948a!] Geneve, Flags [C], vni 0x3, proto TEB (0x6558), options [class Open Virtual Networking (OVN) (0x102) type 0x80(C) len 8 data 00030002]
fa:16:3e:84:56:22 > 52:54:00:f9:f0:f0, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 7305, offset 0, flags [DF], proto ICMP (1), length 84)
172.16.100.10 > 8.8.8.8: ICMP echo request, id 21263, seq 1, length 64
11:39:34.408386 52:54:00:82:23:6d > 52:54:00:ea:65:ed, ethertype IPv4 (0x0800), length 156: (tos 0x0, ttl 64, id 61930, offset 0, flags [DF], proto UDP (17), length 142)
192.168.33.10.57142 > 192.168.33.20.geneve: [bad udp cksum 0xc3fa -> 0x488b!] Geneve, Flags [C], vni 0x1, proto TEB (0x6558), options [class Open Virtual Networking (OVN) (0x102) type 0x80(C) len 8 data 00030002]
fa:16:3e:d0:74:be > fa:16:3e:3c:24:6e, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 108, id 0, offset 0, flags [none], proto ICMP (1), length 84)
8.8.8.8 > 172.16.100.10: ICMP echo reply, id 21263, seq 1, length 64
network-controller 經由geneve tunnel收到ICMP request後,會轉由External Network所使用的br-ex上的eth0上送到網際網路上。另一方面,由網際網路送回來的ICMP reply,先由network-controller的eth0 收到後,會再由geneve tunnel送回給compute-01上的vm。
tcpdump -vvneei eth1 'udp port 6081'
11:39:34.402555 52:54:00:ea:65:ed > 52:54:00:82:23:6d, ethertype IPv4 (0x0800), length 156: (tos 0x0, ttl 64, id 22519, offset 0, flags [DF], proto UDP (17), length 142)
192.168.33.20.51362 > 192.168.33.10.geneve: [bad udp cksum 0xc3fa -> 0x948a!] Geneve, Flags [C], vni 0x3, proto TEB (0x6558), options [class Open Virtual Networking (OVN) (0x102) type 0x80(C) len 8 data 00030002]
fa:16:3e:84:56:22 > 52:54:00:f9:f0:f0, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 7305, offset 0, flags [DF], proto ICMP (1), length 84)
172.16.100.10 > 8.8.8.8: ICMP echo request, id 21263, seq 1, length 64
11:39:34.408378 52:54:00:82:23:6d > 52:54:00:ea:65:ed, ethertype IPv4 (0x0800), length 156: (tos 0x0, ttl 64, id 61930, offset 0, flags [DF], proto UDP (17), length 142)
192.168.33.10.57142 > 192.168.33.20.geneve: [bad udp cksum 0xc3fa -> 0x488b!] Geneve, Flags [C], vni 0x1, proto TEB (0x6558), options [class Open Virtual Networking (OVN) (0x102) type 0x80(C) len 8 data 00030002]
fa:16:3e:d0:74:be > fa:16:3e:3c:24:6e, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 108, id 0, offset 0, flags [none], proto ICMP (1), length 84)
8.8.8.8 > 172.16.100.10: ICMP echo reply, id 21263, seq 1, length 64
tcpdump -i eth0 icmp
11:39:34.403271 IP 10.0.2.211 > dns.google: ICMP echo request, id 21263, seq 1, length 64
11:39:34.408145 IP dns.google > 10.0.2.211: ICMP echo reply, id 21263, seq 1, length 64
今天,我們看完了OpenStack上的VM,如何透過External Network和網際網路溝通。其原理就是使用OVN logical router的SNAT的功能。大家可以再和Day-07: 透過SNAT與DNAT 連至Internet的SNAT架構對照一下,現在再來看,是不是發現作法是完全相同的呢?